package com.boesch.electroOffice.dataaccess.daoImpl;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import com.boesch.electroOffice.dataaccess.common.IllegalDataAccessException;
import com.boesch.electroOffice.dataaccess.common.ReturnCodesDataaccess;
import com.boesch.electroOffice.dataaccess.dao.ChargeDao;
import com.boesch.electroOffice.dataaccess.mapper.ChargeMapper;
import com.boesch.electroOffice.model.electroOffice.Charge;
import com.boesch.electroOffice.utils.DateUtils;
import com.boesch.electroOffice.utils.UserUtils;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.model.User;

/**
 * This class executes the sql statements on the electroOffice database for class Charge.
 * If a Exception is thrown, 
 * it will be unpacked to a illegalDataAccessException 
 * including a return code which can be shown to the user.
 * 
 * @author Ralph Koster
 * 
 */
@Repository
public class ChargeDaoImpl implements ChargeDao, Serializable {

	private static final long serialVersionUID = 8931264716164970702L;
	private static final Log log = LogFactoryUtil.getLog(ChargeDaoImpl.class);

	@Autowired
	private JdbcTemplate eoJdbcTemplate;

	@Value("${electroOffice.queryReadAllCharges}")
	private String queryReadAllCharges;
	@Value("${electroOffice.queryReadChargesByAppointmentId}")
	private String queryReadChargesByAppointmentId;
	@Value("${electroOffice.queryCreateCharge}")
	private String queryCreateCharge;

	/**
	 * {@inheritDoc}
	 */
	public List<Charge> readAllCharges() throws IllegalDataAccessException {
		List<Charge> charges = new ArrayList<Charge>();
		try {
			charges = eoJdbcTemplate.query(queryReadAllCharges, new ChargeMapper());
			return charges;
		} catch (DataAccessException e) {
			throw new IllegalDataAccessException(ReturnCodesDataaccess.NO_OBJECTS_FOUND_ERROR.getValue(), e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public List<Charge> readChargesByAppointmentId(int appointmentId) throws IllegalDataAccessException {
		List<Charge> charges = new ArrayList<Charge>();
		try {
			charges = eoJdbcTemplate.query(queryReadChargesByAppointmentId, new Object[] { appointmentId }, new ChargeMapper());
			return charges;
		} catch (DataAccessException e) {
			throw new IllegalDataAccessException(ReturnCodesDataaccess.NO_OBJECTS_FOUND_ERROR.getValue(), e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public String saveChargeOnDatabase(final Charge charge) throws IllegalDataAccessException {
		final KeyHolder keyHolder = new GeneratedKeyHolder();
		final User currentUser = UserUtils.getCurrentUser();
		try {
			eoJdbcTemplate.update(new PreparedStatementCreator() {
				public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
					PreparedStatement ps = connection.prepareStatement(queryCreateCharge, Statement.RETURN_GENERATED_KEYS);
					ps.setInt(1, charge.getId());
					ps.setDouble(2, charge.getValue());
					ps.setInt(3, charge.getChargeIdentifier().getId());
					ps.setString(4, currentUser.getFullName());
					ps.setTimestamp(5, DateUtils.getCurrentTimestamp());
					ps.setInt(6, 1);
					return ps;
				}
			}, keyHolder);
			log.debug("Inserted charge with id: " + keyHolder.getKey());
			return ReturnCodesDataaccess.CREATED.getValue();
		} catch (DataAccessException e) {
			throw new IllegalDataAccessException(ReturnCodesDataaccess.CREATION_ERROR.getValue(), e);
		}
	}
}
